package com.feilong.edgeAI.speech;

import android.annotation.SuppressLint;
import android.os.Environment;
import android.text.TextUtils;
import android.util.Log;

import com.feilong.edgeAI.speech.util.AbilityConstant;
import com.iflytek.aikit.core.AiAudio;
import com.iflytek.aikit.core.AiHandle;
import com.iflytek.aikit.core.AiHelper;
import com.iflytek.aikit.core.AiInput;
import com.iflytek.aikit.core.AiListener;
import com.iflytek.aikit.core.AiRequest;
import com.iflytek.aikit.core.AiResponse;
import com.iflytek.aikit.core.AiStatus;
import com.iflytek.aikit.core.DataStatus;

import java.io.DataOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created by【仿脑科技】
 * 离线识别
 *
 * @Author: potato
 * @CreateDate: 2023/11/14 15:08
 */
public class EdHelper implements AiListener {
    private static final String TAG = "feilongedgeAI EdHelper";
    private static AiHandle aiHandle;
    private static String ed_dir = AbilityInit.IFLYTEK_ROOT + File.separator + "ed" + File.separator + "encn" + File.separator;

    @SuppressLint("LongLogTag")
    public void init() {

        AiHelper.getInst().registerListener(AbilityConstant.ED_ENCN_ID, this);
        int ret = AiHelper.getInst().engineInit(AbilityConstant.ED_ENCN_ID);
//        int ret = AiHelper.getInst().engineInitNoParams(AbilityConstant.ED_ENCN_ID);
        if (ret != AbilityConstant.ABILITY_SUCCESS_CODE) {
            Log.e(TAG, "EdHelper open ivw error code ===>" + ret);
        }
//        initCustom();
    }

    private DataStatus dataStatus;

    @SuppressLint("LongLogTag")
    public void write(byte[] audio, AiStatus status) {
        AiRequest.Builder dataBuilder = AiRequest.builder();
//        dataBuilder.dataStatus(status);
//        dataBuilder.audio("input", audio);
        AiAudio.Holder PCMData = AiAudio
                .get("PCM") //输入数据key
                .encoding(AiAudio.ENCODING_DEFAULT) //设置音频类型
                .data(audio);//part为 byte[]类型输入数据
        PCMData.status(status);
        dataBuilder.payload(PCMData.valid());
//        Log.d(TAG, "write:audio "+audio.length+" status="+status.name()+" aiHandle="+aiHandle);
//        Log.d(TAG, "write:currentThread= "+Thread.currentThread().getName());
        int ret = AiHelper.getInst().write(dataBuilder.build(), aiHandle);
        if (ret != AbilityConstant.ABILITY_SUCCESS_CODE) {

            Log.e(TAG, "writeData is error =>" + ret + " " + aiHandle);
//            if(null==aiHandle){
//                startRec();
//            }else{
            endAiHandle();
//            }
        } else {
            ret = AiHelper.getInst().read(AbilityConstant.ED_ENCN_ID, aiHandle);
//            saveByteToBin(audio);
            if (ret != AbilityConstant.ABILITY_SUCCESS_CODE) {
                Log.e(TAG, "read error code =>" + ret + " " + aiHandle);
                if (null == aiHandle) {
                    startRec();
                } else {
                    endAiHandle();
                }
            } else {
//                Log.w(TAG, "read success code => $ret");
            }
        }
    }

    private StringBuilder iatRes = new StringBuilder();
    public static final int VADRESPONSETIME = 20 * 1000;
    private boolean engineInit;

    public void initCustom() {
        AiRequest.Builder customBuilder = AiRequest.builder();
        String hotPath = ed_dir + "hotword.txt";
        String replacePath = ed_dir + "replace_list";
        customBuilder.customText("PERSONAL", hotPath, 0);
        customBuilder.customText("PPROC_REPLACE", replacePath, 1);
        int ret = AiHelper.getInst().loadData(AbilityConstant.ED_ENCN_ID, customBuilder.build());
        Log.d(TAG, "EdHelper loadData customBuilder ：" + ret);
        //指定要使用的个性化数据集合，未调用，则默认使用所有loadData加载的数据

        /*
         * indexs 个性化数据索引数组
         */
//        int[] indexs0 = {0};
//        int[] indexs1 = {1};
//        AiHelper.getInst().specifyDataSet(AbilityConstant.ED_ENCN_ID, "PERSONAL", indexs0);
//        AiHelper.getInst().specifyDataSet(AbilityConstant.ED_ENCN_ID, "PPROC_REPLACE", indexs1);
//        if (ret != 0) {
//            Log.e(TAG, "specifyDataSet 失败：" + ret);
//        }
        //        int[] indexs0 = {0};
//        int[] indexs1 = {1};
//        ret = AiHelper.getInst().specifyDataSet(AbilityConstant.ED_ENCN_ID, "PERSONAL", indexs0);
//        if (ret != 0) {
//            Log.e(TAG, "specifyDataSet PERSONAL ：" + ret);
//        }
//        ret = AiHelper.getInst().specifyDataSet(AbilityConstant.ED_ENCN_ID, "PPROC_REPLACE", indexs1);
////        if (ret != 0) {
//            Log.e(TAG, "specifyDataSet PPROC_REPLACE ：" + ret);
////        }
//        initCustom();
    }

    /**
     * 开始识别
     *
     * @return
     */
    public AiHandle startRec() {
        int ret = 0;
        //能力逆初始化， 部分能力，比如语种切换的时候 需要逆初始化
//        AiHelper.getInst().engineUnInit(AbilityConstant.ED_ENCN_ID);
//        ret = AiHelper.getInst().engineInit(AbilityConstant.ED_ENCN_ID);
//        if (ret != AbilityConstant.ABILITY_SUCCESS_CODE) {
//            Log.w(TAG, "open ivw error code ===> $ret" + ret);
//            return null;
//        }
/*        AiRequest.Builder customBuilder = AiRequest.builder();
        String hotPath = ed_dir + "hotword.txt";
        String replacePath = ed_dir + "replace_list";
        customBuilder.customText("PERSONAL", hotPath, 0);
        customBuilder.customText("PPROC_REPLACE", replacePath, 1);
        ret = AiHelper.getInst().loadData(AbilityConstant.ED_ENCN_ID, customBuilder.build());
        Log.d(TAG, "EdHelper loadData customBuilder ：" + ret);

        int[] indexs0 = {0};
        int[] indexs1 = {1};
        ret = AiHelper.getInst().specifyDataSet(AbilityConstant.ED_ENCN_ID, "PERSONAL", indexs0);
        Log.d(TAG, "specifyDataSet PERSONAL ：" + ret);
        ret = AiHelper.getInst().specifyDataSet(AbilityConstant.ED_ENCN_ID, "PPROC_REPLACE", indexs1);
        Log.d(TAG, "specifyDataSet PPROC_REPLACE ：" + ret);*/

        AiInput.Builder paramBuilder = AiInput.builder();
        paramBuilder.param("lmLoad", true);
        paramBuilder.param("vadLoad", true);
        paramBuilder.param("puncLoad", true);
        paramBuilder.param("numLoad", true);
        paramBuilder.param("postprocOn", true);
        paramBuilder.param("lmOn", true);
        paramBuilder.param("vadOn", true);
        paramBuilder.param("vadLinkOn", true);
        paramBuilder.param("vadSpeechEnd", 100);//停止说话后停止识别的时间 100=1秒
        paramBuilder.param("dialectType", 0);
//        paramBuilder.param("vadResponsetime", 500);
        paramBuilder.param("vadResponsetime", VADRESPONSETIME / 10);
        aiHandle = AiHelper.getInst().start(AbilityConstant.ED_ENCN_ID, paramBuilder.build(),
                null);
        if (aiHandle == null) {
            Log.e(TAG, "open esr start失败, handle 为空");
            return null;
        }
        if (aiHandle.getCode() != 0) {
            if (aiHandle.getCode() == 18310) {
                endAiHandle();
                if (edListener != null) {
                    edListener.onError();
                }
            }
            Log.e(TAG, "open esr start失败：" + aiHandle.getCode());
            return aiHandle;
        } else {
            if (edListener != null) {
                edListener.onStart();
            }
        }

        stringBuilder = new StringBuilder();
        IvwHelper.edStatus = AiStatus.BEGIN;
        IvwHelper.edState = true;
//        initWriteFile();
        return aiHandle;

    }

    /**
     * 热词路径
     *
     * @return
     */
    public static String getHostPath() {
        String WORK_DIR = AbilityInit.IFLYTEK_ROOT + File.separator + "ivw";
        return WORK_DIR + File.separator + "keyword.txt";
    }

    /**
     * 结束识别
     */
    public void endAiHandle() {
        IvwHelper.edState = false;
        IvwHelper.edStatus = AiStatus.END;
        Log.d(TAG, "EdHelper EdHelper endAiHandle: ");
        int ret = AiHelper.getInst().end(aiHandle);
        if (ret != AbilityConstant.ABILITY_SUCCESS_CODE) {
//            Log.e(TAG, "endAiHandle is error =>"+ret);

        }
//        endFile();
//        aiHandle = null;
        Log.d(TAG, "EdHelper endAiHandle:currentThread= " + Thread.currentThread().getName());
        Log.e(TAG, "EdHelper endAiHandle is ret =>" + ret);
    }

    private String ProgramAnaly(byte[] buf) throws UnsupportedEncodingException {
        byte[] vsnFileByte = new byte[buf.length];
        System.arraycopy(buf, 0, vsnFileByte, 0, buf.length);
        return new String(vsnFileByte, "GBK");
    }

    private StringBuilder stringBuilder = new StringBuilder();

    /**
     * 识别结果
     *
     * @param id
     * @param outputData
     * @param o
     */
    @Override
    public void onResult(int id, List<AiResponse> outputData, Object o) {
        Log.d(TAG, "onResult: outputData=" + outputData);
        String result = "";
        int status = 0;
        if (null != outputData && outputData.size() > 0) {
            for (int i = 0; i < outputData.size(); i++) {
                AiResponse aiResponse = outputData.get(i);
                status = aiResponse.getStatus();
                String key = outputData.get(i).getKey();
                if (key.contains("plain") || key.contains("pgs") && null != edListener) {
                    byte[] bytes = outputData.get(i).getValue();
                    if (bytes != null) {
                        try {
                            result = ProgramAnaly(bytes);

                            result = replaceStr(result);
                            if (key.contains("pgs")) {
                                edListener.onEdRecognting(result);
                            }
                        } catch (UnsupportedEncodingException e) {
                            e.printStackTrace();
                        }
                        result = byteToString(bytes);
//                        Log.d(TAG, "onResult: ===key=" + key + "  result=" + result);
                    }
                }
            }
        }
//                Log.d(TAG, "识别结果onResult: "+result);
        String pattern = "\"w\":\"(.*?)\",";
        Pattern r = Pattern.compile(pattern);
        StringBuilder sb = new StringBuilder();
        // 现在创建 matcher 对象
        Matcher m = r.matcher(result);
        while (m.find()) {
            if (!m.group(1).equals("。") && !m.group(1).equals("？")) {
                sb.append(m.group(1));
            }
        }
        String res = sb.toString().trim();
        if (res.endsWith(".")) {
            res = res.substring(0, res.length() - 1);
        }
        res = replaceStr(res);
        Log.d(TAG, "EdHelper onResult===: " + res + " length=" + res.length() + " status=" + status);
        if (!TextUtils.isEmpty(res)) {
            stringBuilder.append(res);
        }
        if (status == 2) {
            if (edListener != null) {
                edListener.onEdResult(stringBuilder.toString());
                stringBuilder.delete(0, stringBuilder.length());
            }
            endAiHandle();
           /* final String newName = res;
            if(!TextUtils.isEmpty(res.replaceAll(" ",""))&&null!=currentFile&&currentFile.exists()){
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            Thread.sleep(100);
                            FileUtils.rename(currentFile,(newName+".pcm"));
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }).start();
            }*/
        }
    }

    private String replaceStr(String result) {
        result = result
                .replaceAll("烦恼科技", "仿脑科技")
                .replaceAll("防老科技", "仿脑科技")
                .replaceAll("烦恼之年", "仿脑智联")
                .replaceAll("飞龙吗", "飞龙码")
                .replaceAll("飞龙马", "飞龙码")
                .replaceAll("飞龙心", "飞龙芯")
                .replaceAll("朱班富", "朱邦复")
                .replaceAll("朱邦富", "朱邦复")
                .replaceAll("朱班夫", "朱邦复")
                .replaceAll("朱班夫", "朱邦复")
                .replaceAll("李博思", "李柏思")
                .replaceAll("你博思", "李柏思")
                .replaceAll("李博斯", "李柏思")
                .replaceAll("李柏斯", "李柏思")
                .replaceAll("李百思", "李柏思")
                .replaceAll("李百斯", "李柏思")
                .replaceAll("非龙", "飞龙")
                .replaceAll("尼佳模式", "离家模式")
                .replaceAll("瑜伽模式", "离家模式")
                .replaceAll("泥浆模式", "离家模式")
        ;
        return result;
    }

    @Override
    public void onEvent(int handleID, int event, List<AiResponse> list, Object o) {
        Log.d(TAG, "EdHelper onEvent: event=" + event);

    }

    @Override
    public void onError(int i, int i1, String s, Object o) {
        Log.e(TAG, "EdHelper onError: " + s);
        if (edListener != null) {
            edListener.onError();
        }
    }

    public void saveByteToBin(byte[] bytes) {
        try {
            dos.write(bytes);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void endFile() {
        try {
            fos.flush();
            dos.flush();
            fos.close();
            dos.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private FileOutputStream fos;
    private DataOutputStream dos;
    private String fileName;
    private File currentFile;

    private void initWriteFile() {

        File dir = new File(Environment.getExternalStorageDirectory() + File.separator + "voice");
        if (!dir.exists()) {
            dir.mkdir();
        }
        SimpleDateFormat myFmt3 = new SimpleDateFormat("HH-mm-ss-SSS");
        try {
            fileName = myFmt3.format(new Date(System.currentTimeMillis())) + ".pcm";
            currentFile = new File(dir, fileName);
            fos = new FileOutputStream(currentFile);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        dos = new DataOutputStream(fos);
    }

    public String byteToString(byte[] data) {
        int index = data.length;
        for (int i = 0; i < data.length; i++) {
            if (data[i] == 0) {
                index = i;
                break;
            }
        }
        byte[] temp = new byte[index];
        Arrays.fill(temp, (byte) 0);
        System.arraycopy(data, 0, temp, 0, index);
        String str;
        try {
            str = new String(temp, "GBK");
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return "";
        }
        return str;
    }

    private EdListener edListener;

    public void setEdListener(EdListener edListener) {
        this.edListener = edListener;
    }

    public interface EdListener {
        void onEdRecognting(String result);

        void onEdResult(String result);

        void onError();

        void onStart();
    }
}
